package com.l024.loanthief.socket;

import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.l024.loanthief.constant.APPConstant;
import com.l024.loanthief.entity.ChatMessageEntity;
import com.l024.loanthief.entity.DeviceEntity;
import com.l024.loanthief.entity.UserEntity;
import com.l024.loanthief.eventbus.ChatMessageEvent;
import com.l024.loanthief.utils.DeviceUtil;
import com.l024.loanthief.utils.FileUtil;
import com.l024.loanthief.utils.Logutils;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author wu_ming_zhi_bei
 * @date 2021/1/18 14:29
 * @Notes
 */
public class SocketService {

    //线程池,为并发考虑
    private static ExecutorService mThreadPool;
    private static SocketService socketService;
    private static ServerSocket serverSocket;
    private boolean isEnable;

    private SocketService(){

    };

    public static SocketService getInstance(){
        if(socketService==null){
            synchronized (SocketService.class){
                if(socketService==null){
                    socketService = new SocketService();
                }
            }
        }
        return socketService;
    }
    //初始化服务
    public void init(){
        mThreadPool = Executors.newCachedThreadPool();
        startAsync();
    }

    /**
     * 启动server(异步)
     */
    private void startAsync() {
        isEnable = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                doProcSycn();
            }
        }).start();
    }

    /**
     * 停止Server(异步)
     */
    public void stopAsync() throws IOException {
        if (isEnable) {
            return;
        }
        isEnable = false;
        serverSocket.close();
        serverSocket = null;

    }

    //异步执行
    private void doProcSycn() {
        try {
            InetSocketAddress socketAddress = new InetSocketAddress(APPConstant.PORT);
            serverSocket = new ServerSocket();//创建出ServerSocket对象
            serverSocket.bind(socketAddress);
            while (isEnable) {
                //ServerSocket的accept方法会让ServerSocket一直等在这行代码,
                //直到有远程的Socket对象连入
                final Socket remotePeer = serverSocket.accept();
                mThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        String s = null;
                        try {
                            s = new String("一个远程连接已连接:".getBytes(), "utf-8");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                        Logutils.i(s + remotePeer.getRemoteSocketAddress().toString());
                        onAcceptRemotePeer(remotePeer);
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //处理用户消息
    private void onAcceptRemotePeer(Socket client) {
        try {
            //获取Socket的输出流，用来向客户端发送数据
            PrintStream out = new PrintStream(client.getOutputStream());
            //获取Socket的输入流，用来接收从客户端发送过来的数据
            BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
            boolean flag = true;
            Logutils.e("开始传输啦");
            boolean isFile = false;//是否是文件传输
            String filePath = "";//文件路径
            while (flag) {
                //接收从客户端发送过来的数据
                String str = buf.readLine();
                //解析数据
                if(!TextUtils.isEmpty(str)){
                    Logutils.e("收到消息咯");
                    if(!isFile){
                        if(str.contains(APPConstant.START_FILE)){
                            Logutils.e("开始上传文件");
                            isFile = true;//是文件传输
                            filePath = getFilePath(str);
                            //初始化流
                            initBufferedWriter(filePath);
                        }else{
                            try{
                                ChatMessageEntity messageEntity = JSON.parseObject(str, ChatMessageEntity.class);
                                if(messageEntity!=null){
                                    switch (messageEntity.getType()){
                                        case APPConstant.CONNECT_CODE:{
                                            String msg = messageEntity.getMsg();
                                            UserEntity userEntity = new UserEntity();
                                            if(!TextUtils.isEmpty(msg)){
                                                DeviceEntity deviceEntity = JSON.parseObject(msg, DeviceEntity.class);
                                                if(deviceEntity!=null){
                                                    userEntity.setIcon(deviceEntity.getImgId());
                                                    userEntity.setName(deviceEntity.getPhoneName());
                                                    userEntity.setIp(deviceEntity.getIp());
                                                    //保存连接的用户
                                                    Logutils.e("恭喜"+deviceEntity.getPhoneName()+"链接成功");
                                                }
                                            }
                                            //并且通知更新列表
                                            Logutils.e("客户端连接，更新列表");
                                            EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.ADD_CLIENT,"",userEntity));
                                            //然后返回客户端的服务器的信息
                                            out.println(JSON.toJSONString(new DeviceUtil().getDeviceInfo()));
                                            break;
                                        }
                                        case APPConstant.SEND_TEXT_CODE:{
                                            Logutils.e("收到消息，返回客户端"+str);
                                            //更新ui
                                            EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.RECEIVE_TEXT_CODE,"",messageEntity.getMsg()));
                                            break;
                                        }
                                        case APPConstant.SEND_IMG_CODE:{
                                            String msg = messageEntity.getMsg();
                                            if(!TextUtils.isEmpty(msg)){
                                                EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.RECEIVE_IMG_CODE,"",msg));
                                            }
                                            break;
                                        }
                                    }
                                }
                            }catch (Exception e){
                                Logutils.e("json转换错误："+e.getMessage());
                                EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.SEND_ERROR,"",""));
                            }
                        }
                    }else{
                        Logutils.e("每次数据-->"+str);
                        //当前是文件传输,持续写入文件
                        if(str.contains(APPConstant.END_FILE)){
                            Logutils.e("传输完毕啦");
                            EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.RECEIVE_FILE_CODE,"",filePath));
                            isFile = false;//文件传输完毕
                            closeBufferedWriter();//关闭流
                            //接受到了更新界面
                        }else{
                            receiveFile(str);
                        }
                    }

                }
            }
            out.close();
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //文件流
    private BufferedWriter bw = null;
    private DataOutputStream dos = null;
    /**
     * 初始化流
     */
    private void initBufferedWriter(String filePath){
        try {
            //bw =  new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8));
            dos = new DataOutputStream(new FileOutputStream(filePath,false));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    /**
     * 关闭流
     * @param 】
     */
    private void closeBufferedWriter(){
        try {
            if(dos!=null){
                dos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 写入文件
     * @param content
     */
    private void receiveFile(String content){
       try {
           //bw.write(content);
           dos.writeUTF(content);
       }catch (Exception e){
            e.printStackTrace();
       }
    }

    private String getFilePath(String content){
        if(!TextUtils.isEmpty(content)){
            int i = content.indexOf(APPConstant.START_FILE);
            String fileName =content.substring(0,i).trim();
            Logutils.e("文件名:"+fileName);
            return FileUtil.createFilePath()+File.separator+fileName;
        }
        return "";

    }
    private void receiveFile(Socket socket,String fileName){
        try {
            InputStream inputStream = socket.getInputStream();
            FileOutputStream fileOut = new FileOutputStream(fileName);
            BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOut);
            int temp = 0;
            byte[] buf = new byte[1024];
            Logutils.e("准备吸入"+temp);
            while ((temp = inputStream.read(buf)) != -1) {
                bufferedOutputStream.write(temp);
                Logutils.e("持续写入");
            }
            Logutils.e("写入ok");
            bufferedOutputStream.close();
            fileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
